package com.pi.shisan.web.exception.handler;

import com.alibaba.fastjson2.JSON;
import com.pi.shisan.web.exception.ExceptionPackage;
import lombok.extern.slf4j.Slf4j;
import org.springframework.core.MethodParameter;
import org.springframework.http.converter.HttpMessageNotReadableException;
import org.springframework.validation.BindingResult;
import org.springframework.web.bind.annotation.ControllerAdvice;
import org.springframework.web.bind.annotation.ExceptionHandler;
import org.springframework.web.bind.annotation.ResponseBody;
import org.springframework.web.method.HandlerMethod;
import com.pi.shisan.service.dto.Result;
import com.pi.shisan.service.exception.BusinessException;

import javax.servlet.ServletRequest;
import javax.servlet.ServletResponse;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import java.util.LinkedHashMap;
import java.util.Map;

@Slf4j
@ControllerAdvice
public class GloabExceptionHandler {

    /**
     * 异常时以正确数据结构响应
     * @param request
     * @param handlerMethod
     * @param e
     * @return
     */
    @ResponseBody
    @ExceptionHandler(Exception.class)
    public Result<Void> otherExceptionHandler(HttpServletRequest request, HttpServletResponse response, HandlerMethod handlerMethod, Throwable e) {
        response.setStatus(200);
        if(e instanceof BusinessException){
            if(((BusinessException)e).getCode()== null){
                return Result.err(e.getMessage());
            }else{
                return Result.err(((BusinessException)e).getCode(), e.getMessage());
            }
        }

        if (e instanceof HttpMessageNotReadableException) {
            return Result.err("没有携带参数");
        }

        Object []args = null;
        if(e instanceof ExceptionPackage){
            args = ((ExceptionPackage)e).getArgs();
            e = e.getCause();
        }
        if(args==null || args.length == 0){
            log.error("{}_【全局异常处理】捕获到错误，{}方式请求路径：{}，方法：{},无入参，异常：", handlerMethod.getMethod().getDeclaringClass(),request.getMethod(),request.getRequestURI(),handlerMethod.getMethod().getName(),e);
        }else{
            try{
                Map<String,Object> newArgs = new LinkedHashMap<>(args.length);
                MethodParameter[] parameters = handlerMethod.getMethodParameters();
                for(int i=0;i<parameters.length;i++){
                    MethodParameter p = parameters[i];
                    if(BindingResult.class.isAssignableFrom(p.getParameterType())
                            || ServletRequest.class.isAssignableFrom(p.getParameterType())
                            || ServletResponse.class.isAssignableFrom(p.getParameterType())){
                        continue;
                    }
                    newArgs.put(p.getParameterName(),args[i]);
                }
                log.error("{}_【全局异常处理】捕获到错误，{}方式请求路径：{}，方法：{},入参：{}，异常：", handlerMethod.getMethod().getDeclaringClass(),request.getMethod(),request.getRequestURI(),handlerMethod.getMethod().getName(), JSON.toJSONString(newArgs),e);
            }catch (Exception ex){
                log.error("遇到无法处理的参数，异常信息：",ex);
            }
        }
        return Result.err("系统内部错误");
    }
}
